package org.lex.dbq.model.jdbc.meta;

import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.lex.jdbc.meta.ColumnBean;
import org.lex.jdbc.meta.ForeignKeyBean;
import org.lex.jdbc.meta.PrimaryKeyBean;
import org.lex.jdbc.util.MetaDataHelper;

public class VoConverter {
	public VersionVo[] getVersions(DatabaseMetaData md) throws SQLException {
		// database
		VersionVo db = new VersionVo();
		db.object = "Database";
		db.name = md.getDatabaseProductName();
		db.version = md.getDatabaseProductVersion();
		db.majorVersion = md.getDatabaseMajorVersion();
		db.minorVersion = md.getDatabaseMinorVersion();
		// driver
		VersionVo driver = new VersionVo();
		driver.object = "Driver";
		driver.name = md.getDriverName();
		driver.version = md.getDriverVersion();
		driver.majorVersion = md.getDriverMajorVersion();
		driver.minorVersion = md.getDriverMinorVersion();
		// jdbc
		VersionVo jdbc = new VersionVo();
		jdbc.object = "JDBC";
		jdbc.majorVersion = md.getJDBCMajorVersion();
		jdbc.minorVersion = md.getJDBCMinorVersion();
		return new VersionVo[] { db, driver, jdbc };
	}

	public List<KeyVo> getKeys(DatabaseMetaData md, String catalog, String schema, String table) {
		List<KeyVo> keys = new ArrayList<KeyVo>();
		SQLException ex = null;
		// add pk
		try {
			keys.addAll(this.getPrimaryKeys(md, catalog, schema, table));
		} catch (SQLException e) {
			e.printStackTrace();
			ex = e;
		}
		// add fk
		try {
			keys.addAll(this.getForeignKeys(md, catalog, schema, table));
		} catch (SQLException e) {
			e.printStackTrace();
			ex = e;
		}
		Collections.sort(keys, KeyVo.COMPARATOR);
		return keys;
	}

	// -----------PrimaryKeyBean-----------
	public List<KeyVo> getPrimaryKeys(DatabaseMetaData md, String catalog, String schema, String table) throws SQLException {
		return convertPK(new MetaDataHelper().getPrimaryKeys(md, catalog, schema, table));
	}

	public List<KeyVo> convertPK(Collection<PrimaryKeyBean> beans) {
		List<KeyVo> vos = new ArrayList<KeyVo>();
		for (PrimaryKeyBean bean : beans) {
			vos.add(convertPK(bean));
		}
		return vos;
	}

	public KeyVo convertPK(PrimaryKeyBean bean) {
		KeyVo vo = new KeyVo();
		vo.type = KeyVo.KeyType.PRIMARY;
		vo.name = bean.getPK_NAME();
		vo.columns = bean.getCOLUMN_NAME();
		vo.ordinal = null == bean.getKEY_SEQ() ? 0 : bean.getKEY_SEQ().intValue();
		return vo;
	}

	// -----------PrimaryKeyBean-----------

	// -----------ForeignKeyBean-----------

	public List<KeyVo> getForeignKeys(DatabaseMetaData md, String catalog, String schema, String table) throws SQLException {
		return convertFK(new MetaDataHelper().getImportedForeignKeys(md, catalog, schema, table));
	}

	public List<KeyVo> convertFK(Collection<ForeignKeyBean> beans) {
		List<KeyVo> vos = new ArrayList<KeyVo>();
		for (ForeignKeyBean bean : beans) {
			vos.add(convertFK(bean));
		}
		return vos;
	}

	public KeyVo convertFK(ForeignKeyBean bean) {
		KeyVo vo = new KeyVo();
		vo.type = KeyVo.KeyType.FOREIGN;
		vo.name = bean.getFK_NAME();
		vo.columns = bean.getFKCOLUMN_NAME();
		vo.referenceTable = bean.getPKTABLE_NAME();
		vo.referenceColumn = bean.getPKCOLUMN_NAME();
		return vo;
	}

	// -----------ForeignKeyBean-----------

	// -----------ColumnBean-----------

	public ColumnVo[] getColumns(DatabaseMetaData md, String catalog, String schema, String table, String column)
			throws SQLException {
		List<ColumnBean> list = new MetaDataHelper().getColumns(md, catalog, schema, table, column);
		ColumnVo[] vos = convertColumn(list);
		Arrays.sort(vos, ColumnVo.ORDINAL_COMPARATOR);
		return vos;
	}

	public ColumnVo[] convertColumn(Collection<ColumnBean> beans) {
		ColumnVo[] vos = new ColumnVo[beans.size()];
		int i = 0;
		for (ColumnBean bean : beans) {
			vos[i++] = convertColumn(bean);
		}
		return vos;
	}

	public ColumnVo convertColumn(ColumnBean bean) {
		ColumnVo vo = new ColumnVo();
		// name
		vo.name = bean.getCOLUMN_NAME();
		// type
		String typeName = bean.getTYPE_NAME();
		int columnSize = null == bean.getCOLUMN_SIZE() ? 0 : bean.getCOLUMN_SIZE().intValue();
		int DECIMAL_DIGITS = null == bean.getDECIMAL_DIGITS() ? 0 : bean.getDECIMAL_DIGITS().intValue();
		typeName += "(" + columnSize;
		if (0 != DECIMAL_DIGITS) {
			typeName += "," + DECIMAL_DIGITS;
		}
		typeName += ")";
		vo.type = typeName;
		// comment
		vo.comment = bean.getREMARKS();
		// defualt val
		vo.defaultValue = bean.getCOLUMN_DEF();
		// ordinal
		vo.ordinalPosition = null == bean.getORDINAL_POSITION() ? 0 : bean.getORDINAL_POSITION().intValue();
		// nullable
		vo.nullable = false == "NO".equalsIgnoreCase(bean.getIS_NULLABLE());
		return vo;
	}
	// -----------ColumnBean-----------
}
